#pragma once

#include "NoCopy.hpp"
#include "log.hpp"
#include <cerrno>
#include <cstring>
#include <sys/epoll.h>

class Epoller : public NoCopy
{
public:
    Epoller()
    {
        //创建epoll模型
        _epoll_fd = epoll_create(1);
        if(_epoll_fd == -1)
        {
            lg(Error, "epoll_create error: %s", strerror(errno));
        }
    }

    int EpollerWait(struct epoll_event revents[], int _maxevents)
    {
        //访问就绪队列，获取就绪结构体，返回就绪个数
        int ready_num = epoll_wait(_epoll_fd, revents, _maxevents, _timeout);
        return ready_num;
    }

    void EpollerCtl(int op, int fd, uint32_t event)
    {
        //删除选项
        int n = 0;
        if(op == EPOLL_CTL_DEL)
        {
            n = epoll_ctl(_epoll_fd, op, fd, nullptr);
            if(n == -1)
            {
                lg(Error, "epoll_ctl error: %s", strerror(errno));
            }
        }
        //插入或修改选项
        else
        {
            //构建结构体
            struct epoll_event ep_event;
            ep_event.data.fd = fd;
            ep_event.events = event;

            //将结构体插入或修改到红黑树中
            n = epoll_ctl(_epoll_fd, op, fd, &ep_event);
            if(n == -1)
            {
                lg(Error, "epoll_ctl error: %s", strerror(errno));
            }
        }
    }

    ~Epoller()
    {
        //关闭_epoll_fd
        if(_epoll_fd >= 0)
        {
            close(_epoll_fd);
        }
    }

private:
    int _epoll_fd; //epoll模型
    int _timeout{1000}; //等待时间
};